#include <utility>                   // for std::pair
#include <algorithm>                 // for std::for_each
#include <vector>
#include <boost/graph/graph_traits.hpp>
#include <boost/graph/adjacency_list.hpp>
#include <boost/config.hpp>
#include <boost/graph/graphviz.hpp>
#include <boost/property_map.hpp>
#include <boost/graph/adjacency_iterator.hpp>
#include <boost/graph/properties.hpp>
#include <boost/graph/graph_utility.hpp>
#include <boost/graph/iteration_macros.hpp>
#include <boost/bimap.hpp>



using namespace boost;
using namespace std;


/**
 *@enum edge_portout_t
 *@brief mapping through edge and own out port.
 */
enum edge_portout_t { edge_portout };
/**
 *@enum edge_portin_t
 *@brief mapping through edge and own in port.
 */
enum edge_portin_t { edge_portin };
/**
 *@enumvertex_site_t
 *@brief mapping through vertex and own site.
 */
enum vertex_site_t { vertex_site };

namespace boost {
  BOOST_INSTALL_PROPERTY(edge, portout);
  BOOST_INSTALL_PROPERTY(edge, portin);
  BOOST_INSTALL_PROPERTY(vertex, site);
}

/**
 *@typedef define a edge property to assign a edge in port.
 */
typedef property<edge_portin_t, string > Porti;
/**
 *@typedef define a edge property that group a edge out port and a edge in port.
 */
typedef property<edge_portout_t, string, Porti> Ports;
/**
 *@typedef define a property edge name that group all previous edge properties.
 */
typedef property<edge_name_t, string, Ports> Edge_Name;
/**
 *@typedef define a property verte site to store the location of element.
 */
typedef property<vertex_site_t, string> Site;



/**
 *@typedef define the graph used to store the XDL info.
 */
typedef adjacency_list<
  listS,       // Store out-edges of each vertex in a std::list
  listS,       // Store vertex set in a std::list
  directedS, // The file dependency graph is directed
  
  /* vertex properties */
  property<vertex_name_t, string, Site >,
  /* edge properties */
  Edge_Name
  //property<edge_name_t, string, Porto>
> Graph;


/**
 *@typedef define a Vertex alias of vertex_descriptor.
 */
typedef graph_traits<Graph>::vertex_descriptor Vertex;
/**
 *@typedef define a property map for vertex and its name.
 */
typedef property_map<Graph, vertex_name_t>::type name_map_t;
/**
 *@typedef define a property map for vertex and its site.
 */
typedef property_map<Graph, vertex_site_t>::type site_map_t;

/**
 *@typedef define a Edge alias of edge_descriptor.
 */
typedef graph_traits<Graph>::edge_descriptor Edge;
//typedef graph_traits<Graph>::vertex_descriptor Vertex;
/**
 *@typedef define a property map for edge and its name.
 */
typedef property_map<Graph, edge_name_t>::type edge_map_t;
/**
 *@typedef define a property map for edge and its out port.
 */
typedef property_map<Graph, edge_portout_t>::type portout_map;
/**
 *@typedef define a property map for edge and its in port.
 */
typedef property_map<Graph, edge_portin_t>::type portin_map;

typedef graph_traits<Graph>::out_edge_iterator out_iter;
typedef graph_traits<Graph>::in_edge_iterator in_iter;
typedef graph_traits<Graph>::edge_iterator edge_iterator;
typedef graph_traits<Graph>::vertex_iterator vertex_iterator;
typedef adjacency_iterator_generator<Graph, Vertex, out_iter>::type adjacency_iterator;
typedef inv_adjacency_iterator_generator<Graph, Vertex, in_iter>::type inv_adjacency_iterator;




/* to find the vertex by the string */
typedef map< string, Vertex > map_vertex;

typedef map< string, Vertex > map_site;

/* to retrieve the line number of vertex in xdl file */
typedef map< Vertex, int > map_vertex_line;

/* to retrieve the line number of edge(net) in xdl file */
typedef map< Edge, pair < int, int > > map_edge_line;


/**
 *Use bimap to retrieve the info both with the key and value.
 */
typedef bimap< Vertex, string > bm_vertex;


#ifndef _MYGRAPH_H_
#define _MY_GRAPH_H_


/**
 *@class MyGraph
 *@brief This class is used to define the graph for XDL file.
 */

class MyGraph: public Graph {


	public:
		MyGraph();

                /**
		 *Add the vertex to the graph.
		 *@param[in] name a string pointer: vertex name.
                 *@param[in] _line reference to file's line number.
		 */
		void addVertex(string* name, int _line);

                string getVertexName(Vertex target);
                
                string getVertexSite(Vertex target);

		void setSite(string* site);

		Vertex getVertexBySite(string* site);

                int getVertexLine(Vertex target);

                vector < pair<int,int> >* getNetLines(Vertex target);

                bm_vertex* getVertexMap();

                /**
		 *Set the out port of edge.
		 *@param[in] vertex a string pointer: vertex name.
		 *@param[in] out_pin a string pointer: the out port name.
		 */
                void setOutPin(string* vertex, string* out_pin, int _line);

                void addInPin(string* vertex, string* in_pin, int _line);
		/**
		 *Set the edge name, useful to label the graphviz graph edge.
		 *@param[in] name a string pointer: name of the edge.
		 */
                void setNet(string* name);
                /**
		 *Set the edge name, useful to label the graphviz graph edge.
		 *@param[in] name a string pointer: name of the edge.
                 *@param[in] type a string pointer; type of net.
		 */
		void setNet(string* name, string* type);
                /**
		 *Return a pointer to the dynamic properties of the graph.
		 */
		dynamic_properties* getDProperties();
                /**
		 *Set the dynamic properties to use into graphviz file.
		 */
		void setDProperties();
                /**
		 *Write into graphviz format the graph.
		 */
		void writeGraph(char* _filename);

                
		
	private:
		/**
		 *Mapping the vertex with its own name.
		 */
		name_map_t name_map;

                /**
                 *Mapping the vertex with its own site.
                 */
		site_map_t site_map;
                /**
		 *Mapping the edge with its own name.
		 */
		edge_map_t edge_map;
	
		/**
		 *Mapping the edge with out port.
		 */
		portout_map port_out;
                /**
		 *Mapping the edge with in port.
		 */
		portin_map port_in;
	
		/**
		 *Mapping the vertex name with vertex object.
		 */
		map_vertex name_vertex;
		/* to retrieve the line number of vertex in xdl file */
		map_vertex_line vertex_line;
                /* to retrieve the line number of vertex in xdl file */
		map_edge_line edge_line;
		/* support to find the vertix with name */
		map_site site_vertex;

                /**
		 *An edge iterators to scan the map of edges.
		 */
		graph_traits<Graph>::edge_iterator ei, ei_end;

                /**
		 *An vertex iterators to scan the map of vertex.
		 */
		graph_traits<Graph>::vertex_iterator i, end; //iterator to visit the graph
		
		/*
		 *Edge object.
		 */
		graph_traits<Graph>::edge_descriptor ed;

                /**
		 *This object provides the property of the vertex and edege to write it down into ghraph file.
		 */
		dynamic_properties dp;

                /**
		 * vertex descriptor variables to support the inserting edge process.
		 */
                Vertex src, dest, tmp;

                /**
		 * string pointer variables to support the inserting edge process.
		 */
		string* pin_name_tmp, name_tmp, file_name;

                /**
		 *Vector that store the destination vertex and in port of a net to store in a second moment.
		 */
		vector< pair<Vertex, string* > > list;
                
                vector<int> list_in_pin_line;

                int out_pin_line;

                vector< pair<int,int> > net_list;


                bm_vertex vert_bm;

                
};



#endif
